package com.kapark.cloud.utils;


import javax.sound.sampled.AudioFormat;

/**
 * @author: hyzhan
 * @date: 2019/6/13
 * @desc: TODO
 */
public class AMAudioFormat {
    public static final int FORMAT_CODE_CD = 1;
    public static final int FORMAT_CODE_FM = 2;
    public static final int FORMAT_CODE_TELEPHONE = 3;
    public static final int FORMAT_CODE_GSM = 4;
    public static final String[] FORMAT_NAMES = {
            "Cell phone GSM (13.2KBit/s - Modem)",
            "Telephone ulaw (64KBit/s - ISDN)",
            "FM quality mono (352.8KBit/s - ADSL)",
            "CD quality mono (705.6KBit/s - LAN)"
    };
    public static final int[] FORMAT_CODES = {
            FORMAT_CODE_GSM,
            FORMAT_CODE_TELEPHONE,
            FORMAT_CODE_FM,
            FORMAT_CODE_CD
    };
    public static final int FORMAT_CODE_DEFAULT = FORMAT_CODE_GSM;
    private static int SAMPLE_RATE;
    // always using lines with 16 bit
    private static float LINE_FRAME_SIZE = 2.0f;
    private static float NET_BYTES_PER_SAMPLE;
    // quick look-up tables
    private static final float[] netFrameSize = {
            1, // nothing
            2, // CD
            2, // FM
            1, // Telephone
            33.0f // GSM
    };
    private static final float[] netSampleRate = {
            1.0f,  // nothing
            44100.0f, // CD
            22050.0f, // FM
            8000.0f,  // Telephone
            8000.0f   // GSM
    };
    private static final float[] netFrameRate = {
            1.0f,  // nothing
            44100.0f, // CD
            22050.0f, // FM
            8000.0f,  // Telephone
            50.0f   // GSM
    };

    public static long lineBytes2Ms(long bytes) {
        return (long) (bytes / LINE_FRAME_SIZE * 1000 / SAMPLE_RATE);
    }

    public static long netBytes2Ms(long bytes, int formatCode) {
        return (long) (bytes / netFrameRate[formatCode] * 1000 / netFrameSize[formatCode]);
    }

    public static long bytes2Ms(long bytes, AudioFormat format) {
        return (long) (bytes / format.getFrameRate() * 1000 / format.getFrameSize());
    }

    public static long ms2Bytes(long ms, AudioFormat format) {
        return (long) (ms * format.getFrameRate() / 1000 * format.getFrameSize());
    }

    /**
     * @param formatCode 整型音频格式代号
     * @return 根据传递音频格式代号生成的AudioFormat对象
     */
    public static AudioFormat getLineAudioFormat(int formatCode) {
        return getLineAudioFormat(netSampleRate[formatCode]);
    }

    public static AudioFormat getLineAudioFormat(float sampleRate) {
        return new AudioFormat(
                AudioFormat.Encoding.PCM_SIGNED,
                sampleRate,    // sampleRate
                16,            // sampleSizeInBits
                1,             // channels
                2,             // frameSize
                sampleRate,    // frameRate
                false);        // bigEndian
        // ulaw conversion does not work with Sun's ulaw provider if big endian...
    }

    public static AudioFormat getNetAudioFormat(int nformat) {
        if (nformat == FORMAT_CODE_CD) {
            return new AudioFormat(
                    AudioFormat.Encoding.PCM_SIGNED,
                    44100.0f,   // sampleRate
                    16,            // sampleSizeInBits
                    1,             // channels
                    2,             // frameSize
                    44100.0f,      // frameRate
                    true);         // bigEndian
        } else if (nformat == FORMAT_CODE_FM) {
            return new AudioFormat(
                    AudioFormat.Encoding.PCM_SIGNED,
                    22050.0f,   // sampleRate
                    16,            // sampleSizeInBits
                    1,             // channels
                    2,             // frameSize
                    22050.0f,      // frameRate
                    true);         // bigEndian
        } else if (nformat == FORMAT_CODE_TELEPHONE) {
            return new AudioFormat(
                    AudioFormat.Encoding.ULAW,
                    8000.0f,       // sampleRate
                    8,             // sampleSizeInBits
                    1,             // channels
                    1,             // frameSize
                    8000.0f,       // frameRate
                    false);        // bigEndian
        } else if (nformat == FORMAT_CODE_GSM) {
            try {
                Class.forName("org.tritonus.share.sampled.Encodings");
            } catch (ClassNotFoundException cnfe) {
                throw new RuntimeException("Tritonus shared classes not properly installed!");
            }
            return new AudioFormat(org.tritonus.share.sampled.Encodings.getEncoding("GSM0610"),
                    8000.0F,        // sampleRate
                    -1,             // sampleSizeInBits
                    1,              // channels
                    33,             // frameSize
                    50.0F,          // frameRate
                    false);         // bigEndian
        }
        throw new RuntimeException("Wrong format code!");
    }

    public static int getFormatCode(AudioFormat format) {
        AudioFormat.Encoding encoding = format.getEncoding();
        // very simple check...
        if (encoding.equals(AudioFormat.Encoding.PCM_SIGNED)) {
            if (format.getSampleRate() == 44100.0f) {
                return FORMAT_CODE_CD;
            } else {
                return FORMAT_CODE_FM;
            }
        }
        if (encoding.equals(AudioFormat.Encoding.ULAW)) {
            return FORMAT_CODE_TELEPHONE;
        }
        if (encoding.equals(org.tritonus.share.sampled.Encodings.getEncoding("GSM0610"))) {
            return FORMAT_CODE_GSM;
        }
        throw new RuntimeException("Wrong Format");
    }
}
